import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from pyecharts.charts import Line, Bar, Pie, Map
from pyecharts import options as opts
from pyecharts.globals import ThemeType

# 设置中文字体
matplotlib.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
matplotlib.rcParams['axes.unicode_minus'] = False

# 设置显示所有列
pd.set_option('display.max_columns', None)

def load_data():
    """加载数据文件，处理编码问题"""
    try:
        # 尝试不同的编码方式
        encodings = ['utf-8', 'gbk', 'gb2312', 'gb18030']
        
        # 加载广播电视数据
        broadcast_data = None
        for encoding in encodings:
            try:
                broadcast_data = pd.read_csv('数据文件/广播电视情况.csv', encoding=encoding)
                print(f"广播电视数据加载成功，使用编码: {encoding}")
                break
            except UnicodeDecodeError:
                continue
        
        # 加载人口年龄结构数据
        population_data = None
        for encoding in encodings:
            try:
                population_data = pd.read_csv('数据文件/人口年龄结构.csv', encoding=encoding)
                print(f"人口数据加载成功，使用编码: {encoding}")
                break
            except UnicodeDecodeError:
                continue
        
        # 加载房地产投资数据
        realestate_data = None
        for encoding in encodings:
            try:
                realestate_data = pd.read_csv('数据文件/2024年12月全国地区房地产投资累计值.csv', encoding=encoding)
                print(f"房地产数据加载成功，使用编码: {encoding}")
                break
            except UnicodeDecodeError:
                continue
                
        return broadcast_data, population_data, realestate_data
    except Exception as e:
        print(f"数据加载错误: {e}")
        return None, None, None

def task1_cable_tv_users(broadcast_data):
    """任务一：有线广播电视用户数情况折线图"""
    print("\n=== 任务一：有线广播电视用户数情况 ===")
    
    # 提取2019-2023年数据
    years = ['2019年', '2020年', '2021年', '2022年', '2023年']
    
    # 查找对应的行数据
    national_row = broadcast_data[broadcast_data.iloc[:, 0].str.contains('全国有线广播电视用户数', na=False)]
    rural_row = broadcast_data[broadcast_data.iloc[:, 0].str.contains('农村有线广播电视用户数', na=False)]
    
    if len(national_row) > 0 and len(rural_row) > 0:
        # 提取数据
        national_data = []
        rural_data = []
        
        for year in years:
            if year in broadcast_data.columns:
                nat_val = national_row[year].iloc[0]
                rur_val = rural_row[year].iloc[0]
                
                # 处理数据，转换为数值
                try:
                    national_data.append(float(nat_val) if pd.notna(nat_val) and nat_val != '' else 0)
                    rural_data.append(float(rur_val) if pd.notna(rur_val) and rur_val != '' else 0)
                except:
                    national_data.append(0)
                    rural_data.append(0)
        
        # 使用pyecharts绘制折线图
        line = (
            Line(init_opts=opts.InitOpts(theme=ThemeType.MACARONS, width="800px", height="600px"))
            .add_xaxis([year.replace('年', '') for year in years])
            .add_yaxis("全国有线广播电视用户数", national_data, is_smooth=True)
            .add_yaxis("农村有线广播电视用户数", rural_data, is_smooth=True)
            .set_global_opts(
                title_opts=opts.TitleOpts(
                    title="5年期间有线广播电视用户数情况",
                    subtitle="单位：万户",
                    pos_left="center"
                ),
                xaxis_opts=opts.AxisOpts(name="年份"),
                yaxis_opts=opts.AxisOpts(name="用户数"),
                legend_opts=opts.LegendOpts(pos_top="10%")
            )
        )
        
        line.render("任务一_有线广播电视用户数情况.html")
        print("任务一图表已生成：任务一_有线广播电视用户数情况.html")
        
        # 使用matplotlib绘制备用图表
        plt.figure(figsize=(10, 6))
        years_simple = [year.replace('年', '') for year in years]
        plt.plot(years_simple, national_data, marker='o', label='全国有线广播电视用户数', linewidth=2)
        plt.plot(years_simple, rural_data, marker='s', label='农村有线广播电视用户数', linewidth=2)
        plt.title('5年期间有线广播电视用户数情况\n单位：万户', fontsize=14, pad=20)
        plt.xlabel('年份', fontsize=12)
        plt.ylabel('用户数', fontsize=12)
        plt.legend()
        plt.grid(True, alpha=0.3)
        plt.tight_layout()
        plt.savefig('任务一_有线广播电视用户数情况_matplotlib.png', dpi=300, bbox_inches='tight')
        plt.show()
    else:
        print("未找到相关数据行")

def task2_movie_box_office(broadcast_data):
    """任务二：国产和进口电影票房收入情况柱状图"""
    print("\n=== 任务二：国产和进口电影票房收入情况 ===")
    
    years = ['2019年', '2020年', '2021年', '2022年', '2023年']
    
    # 查找电影票房数据
    domestic_row = broadcast_data[broadcast_data.iloc[:, 0].str.contains('国产电影票房收入', na=False)]
    import_row = broadcast_data[broadcast_data.iloc[:, 0].str.contains('进口电影票房收入', na=False)]
    
    if len(domestic_row) > 0 and len(import_row) > 0:
        domestic_data = []
        import_data = []
        
        for year in years:
            if year in broadcast_data.columns:
                dom_val = domestic_row[year].iloc[0]
                imp_val = import_row[year].iloc[0]
                
                try:
                    domestic_data.append(float(dom_val) if pd.notna(dom_val) and dom_val != '' else 0)
                    import_data.append(float(imp_val) if pd.notna(imp_val) and imp_val != '' else 0)
                except:
                    domestic_data.append(0)
                    import_data.append(0)
        
        # 使用pyecharts绘制柱状图
        bar = (
            Bar(init_opts=opts.InitOpts(theme=ThemeType.MACARONS, width="800px", height="600px"))
            .add_xaxis([year.replace('年', '') for year in years])
            .add_yaxis("国产电影票房收入", domestic_data)
            .add_yaxis("进口电影票房收入", import_data)
            .set_global_opts(
                title_opts=opts.TitleOpts(
                    title="5年期间国产和进口电影票房收入",
                    subtitle="单位：亿元",
                    pos_left="center"
                ),
                xaxis_opts=opts.AxisOpts(name="年份"),
                yaxis_opts=opts.AxisOpts(name="票房收入"),
                legend_opts=opts.LegendOpts(orient="vertical", pos_right="5%", pos_top="15%")
            )
        )
        
        bar.render("任务二_国产和进口电影票房收入.html")
        print("任务二图表已生成：任务二_国产和进口电影票房收入.html")
        
        # 使用matplotlib绘制备用图表
        plt.figure(figsize=(10, 6))
        x = np.arange(len(years))
        width = 0.35
        years_simple = [year.replace('年', '') for year in years]
        
        plt.bar(x - width/2, domestic_data, width, label='国产电影票房收入', alpha=0.8)
        plt.bar(x + width/2, import_data, width, label='进口电影票房收入', alpha=0.8)
        
        plt.title('5年期间国产和进口电影票房收入\n单位：亿元', fontsize=14, pad=20)
        plt.xlabel('年份', fontsize=12)
        plt.ylabel('票房收入', fontsize=12)
        plt.xticks(x, years_simple)
        plt.legend()
        plt.grid(True, alpha=0.3, axis='y')
        plt.tight_layout()
        plt.savefig('任务二_国产和进口电影票房收入_matplotlib.png', dpi=300, bbox_inches='tight')
        plt.show()
    else:
        print("未找到电影票房数据")

def task3_population_structure(population_data):
    """任务三：人口年龄结构与抚养比情况"""
    print("\n=== 任务三：人口年龄结构与抚养比情况 ===")
    
    # 获取2023年数据
    year_col = '2023年'
    
    if year_col in population_data.columns:
        # 提取人口年龄结构数据
        age_0_14_row = population_data[population_data.iloc[:, 0].str.contains('0-14岁人口', na=False)]
        age_15_64_row = population_data[population_data.iloc[:, 0].str.contains('15-64岁人口', na=False)]
        age_65_plus_row = population_data[population_data.iloc[:, 0].str.contains('65岁及以上人口', na=False)]
        
        # 提取抚养比数据
        total_ratio_row = population_data[population_data.iloc[:, 0].str.contains('总抚养比', na=False)]
        child_ratio_row = population_data[population_data.iloc[:, 0].str.contains('少儿抚养比', na=False)]
        elderly_ratio_row = population_data[population_data.iloc[:, 0].str.contains('老年抚养比', na=False)]
        
        try:
            # 人口数据（万人）
            age_0_14 = float(age_0_14_row[year_col].iloc[0]) if len(age_0_14_row) > 0 else 0
            age_15_64 = float(age_15_64_row[year_col].iloc[0]) if len(age_15_64_row) > 0 else 0
            age_65_plus = float(age_65_plus_row[year_col].iloc[0]) if len(age_65_plus_row) > 0 else 0
            
            # 抚养比数据（%）
            total_ratio = float(total_ratio_row[year_col].iloc[0]) if len(total_ratio_row) > 0 else 0
            child_ratio = float(child_ratio_row[year_col].iloc[0]) if len(child_ratio_row) > 0 else 0
            elderly_ratio = float(elderly_ratio_row[year_col].iloc[0]) if len(elderly_ratio_row) > 0 else 0
            
            print(f"提取的数据：")
            print(f"人口结构 - 0-14岁：{age_0_14}万人，15-64岁：{age_15_64}万人，65岁以上：{age_65_plus}万人")
            print(f"抚养比 - 总抚养比：{total_ratio}%，少儿抚养比：{child_ratio}%，老年抚养比：{elderly_ratio}%")
            
            # 人口年龄结构数据
            population_data_list = [
                ["0～14岁人口", age_0_14],
                ["15～64岁人口", age_15_64],
                ["65岁及以上人口", age_65_plus]
            ]
            
            # 抚养比数据
            ratio_data_list = [
                ["总抚养比", total_ratio],
                ["少儿抚养比", child_ratio],
                ["老年抚养比", elderly_ratio]
            ]
            
            # 创建组合饼图
            pie_combined = (
                Pie(init_opts=opts.InitOpts(theme=ThemeType.MACARONS, width="900px", height="600px"))
                .add(
                    "人口年龄结构",
                    population_data_list,
                    radius=["20%", "45%"],
                    center=["25%", "50%"],
                    rosetype="radius"
                )
                .add(
                    "抚养比",
                    ratio_data_list,
                    radius=["20%", "45%"],
                    center=["75%", "50%"]
                )
                .set_global_opts(
                    title_opts=opts.TitleOpts(
                        title="2023年人口年龄结构与抚养比情况",
                        subtitle="人口单位：万人  抚养比单位：%",
                        pos_left="center"
                    ),
                    legend_opts=opts.LegendOpts(
                        orient="horizontal",
                        pos_left="center",
                        pos_bottom="5%"
                    ),
                    tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a} {b}: {c} ({d}%)")
                )
                .set_series_opts(
                    label_opts=opts.LabelOpts(formatter="{b}：{c}")
                )
            )
            
            pie_combined.render("任务三_人口年龄结构与抚养比情况.html")
            print("任务三图表已生成：任务三_人口年龄结构与抚养比情况.html")
            
            # 使用matplotlib绘制备用图表
            fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))
            
            # 人口年龄结构饼图
            labels1 = ['0～14岁人口', '15～64岁人口', '65岁及以上人口']
            sizes1 = [age_0_14, age_15_64, age_65_plus]
            colors1 = ['#ff9999', '#66b3ff', '#99ff99']
            
            ax1.pie(sizes1, labels=labels1, colors=colors1, autopct='%1.1f%%', startangle=90)
            ax1.set_title('人口年龄结构\n(单位：万人)')
            
            # 抚养比圆环图
            labels2 = ['总抚养比', '少儿抚养比', '老年抚养比']
            sizes2 = [total_ratio, child_ratio, elderly_ratio]
            colors2 = ['#ffcc99', '#ff99cc', '#c2c2f0']
            
            wedges, texts, autotexts = ax2.pie(sizes2, labels=labels2, colors=colors2, 
                                             autopct='%1.1f%%', startangle=90, 
                                             wedgeprops=dict(width=0.5))
            ax2.set_title('抚养比情况\n(单位：%)')
            
            plt.suptitle('2023年人口年龄结构与抚养比情况', fontsize=16, y=0.95)
            plt.tight_layout()
            plt.savefig('任务三_人口年龄结构与抚养比情况_matplotlib.png', dpi=300, bbox_inches='tight')
            plt.show()
            
        except Exception as e:
            print(f"处理人口数据时出错: {e}")
    else:
        print("未找到2023年人口数据")

def task4_real_estate_map(realestate_data):
    """任务四：全国地区房地产投资累计情况地图"""
    print("\n=== 任务四：全国地区房地产投资累计情况 ===")
    
    try:
        # 处理地区名称，统一格式
        provinces = []
        values = []
        
        for index, row in realestate_data.iterrows():
            province = str(row.iloc[0]).strip()
            value = float(row.iloc[1])
            
            # 统一省份名称格式
            province_mapping = {
                '北京市': '北京', '天津市': '天津', '上海市': '上海', '重庆市': '重庆',
                '河北省': '河北', '山西省': '山西', '辽宁省': '辽宁', '吉林省': '吉林',
                '黑龙江省': '黑龙江', '江苏省': '江苏', '浙江省': '浙江', '安徽省': '安徽',
                '福建省': '福建', '江西省': '江西', '山东省': '山东', '河南省': '河南',
                '湖北省': '湖北', '湖南省': '湖南', '广东省': '广东', '海南省': '海南',
                '四川省': '四川', '贵州省': '贵州', '云南省': '云南', '陕西省': '陕西',
                '甘肃省': '甘肃', '青海省': '青海', '台湾省': '台湾',
                '内蒙古自治区': '内蒙古', '广西壮族自治区': '广西', '西藏自治区': '西藏',
                '宁夏回族自治区': '宁夏', '新疆维吾尔自治区': '新疆',
                '香港特别行政区': '香港', '澳门特别行政区': '澳门'
            }
            
            # 标准化省份名称
            for full_name, short_name in province_mapping.items():
                if province == full_name or province == short_name:
                    province = short_name
                    break
            
            provinces.append(province)
            values.append(value)
        
        # 创建地图数据
        map_data = list(zip(provinces, values))
        
        # 计算数值范围用于visualmap
        min_val = min(values)
        max_val = max(values)
        
        # 创建地图
        map_chart = (
            Map(init_opts=opts.InitOpts(theme=ThemeType.MACARONS, width="1000px", height="700px"))
            .add("房地产投资累计值", map_data, "china")
            .set_global_opts(
                title_opts=opts.TitleOpts(
                    title="2024年12月全国地区房地产投资累计值",
                    subtitle="单位：亿元",
                    pos_left="center"
                ),
                visualmap_opts=opts.VisualMapOpts(
                    max_=max_val,
                    min_=min_val,
                    range_text=["高", "低"],
                    is_calculable=True,
                    range_color=["#D7DA8B", "#E15457"],
                    pieces=[
                        {"min": 0, "max": 1000, "label": "0-1000亿", "color": "#D7DA8B"},
                        {"min": 1000, "max": 5000, "label": "1000-5000亿", "color": "#E1C568"},
                        {"min": 5000, "max": 10000, "label": "5000-10000亿", "color": "#E89C3C"},
                        {"min": 10000, "max": 15000, "label": "10000-15000亿", "color": "#E15457"},
                        {"min": 15000, "label": "15000亿以上", "color": "#B03A5B"}
                    ]
                )
            )
            .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
        )
        
        map_chart.render("任务四_全国地区房地产投资累计值地图.html")
        print("任务四图表已生成：任务四_全国地区房地产投资累计值地图.html")
        
        # 打印数据统计信息
        print(f"数据统计：")
        print(f"最大值：{max_val:.2f}亿元（{provinces[values.index(max_val)]}）")
        print(f"最小值：{min_val:.2f}亿元（{provinces[values.index(min_val)]}）")
        print(f"平均值：{np.mean(values):.2f}亿元")
        
    except Exception as e:
        print(f"处理房地产数据时出错: {e}")

def main():
    """主函数"""
    print("开始数据可视化任务...")
    
    # 加载数据
    broadcast_data, population_data, realestate_data = load_data()
    
    if broadcast_data is not None:
        print("\n广播电视数据预览：")
        print(broadcast_data.head())
        
        # 执行任务一和任务二
        task1_cable_tv_users(broadcast_data)
        task2_movie_box_office(broadcast_data)
    
    if population_data is not None:
        print("\n人口数据预览：")
        print(population_data.head())
        
        # 执行任务三
        task3_population_structure(population_data)
    
    if realestate_data is not None:
        print("\n房地产数据预览：")
        print(realestate_data.head())
        
        # 执行任务四
        task4_real_estate_map(realestate_data)
    
    print("\n所有数据可视化任务完成！")
    print("生成的文件：")
    print("- 任务一_有线广播电视用户数情况.html")
    print("- 任务一_有线广播电视用户数情况_matplotlib.png")
    print("- 任务二_国产和进口电影票房收入.html")
    print("- 任务二_国产和进口电影票房收入_matplotlib.png")
    print("- 任务三_人口年龄结构与抚养比情况.html")
    print("- 任务三_人口年龄结构与抚养比情况_matplotlib.png")
    print("- 任务四_全国地区房地产投资累计值地图.html")

if __name__ == "__main__":
    main() 